/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package combo;



/**
 * Class is used for the return of permutations of Objects.
 * @author CJ
 */
public class Combo {

    /** Main driver method that is used for the permutaion of Objects.
     *
     * @param storage The array of objects wished to be see as permutations
     * @return The 2D array where each array is a permutations of the param
     */
    public static Object[][] driver(Object[] storage)
    {

      
        Object result[][] = generateCombos(new Object[][]{storage});
        for(int i = 0;i < result.length;++i)
        {
            for(int x = 0; x < result[i].length;++x)
                System.out.print((Integer)(result[i][x]));
            System.out.println();
        }
        //System.out.println(result.length);
        return result;
    }

    private static Object[][] generateCombos(Object[][] storage)
    {
        if(storage[0].length == 0)
            return storage;

        Object[][] result = new Object[fib(storage[0].length)][storage[0].length];

        int currenty = 0;

        for(int y = 0; y < storage.length; ++y)
        {
            for(int x = 0; x < storage[y].length; ++x)
            {
                Object[][] out = generateCombos(new Object[][] {cut(storage[y], x)});

                for(int i = 0; i < out.length; ++i)
                {
                    result[currenty] = grapt(out[i], storage[y][x]);
                    ++currenty;
                }
            }
        }
        return result;
    }

    private static Object[] cut(Object[] storage, int place)
    {
        Object[] result = new Object[storage.length - 1];
        int x = 0;
        for(int i = 0;i<storage.length;++i)
        {
            if(i == place)
                continue;
            result[x] = storage[i];
            ++x;
        }
        return result;
    }

    private static Object[] grapt(Object[] storage, Object add)
    {
        Object[] result = new Object[storage.length + 1];
        for(int i = 0;i < storage.length;++i)
        {
            result[i] = storage[i];
        }
        result[storage.length] = add;

        return result;
    }


    private static int fib(int x)
    {
        int result = 1;
        for(int i = 2;i<=x;++i)
            result *= i;
        return result;
    }
}
